I need to have child objects be assigned an attribute that contains the child's parent's header number. For example: |
Re: Getting parent header number WARNING: I just realized the attr-DXL solution below fails to take into account:
Use Attr-DXL.
It seems the requirement is that it will display the object's own paragraph number if its a heading, or if its a text object then display the nearest ancestor's Heading. Thus in your example, the attr-DXL will display "3.1" for both your objects. Perhaps the name of the target attribute is "dxlSectionNumber".
//**************************
bool fIsTable(Object obj)
{ // Is the object part of a DOORS table?
if (null obj) return(false)
return (row(obj) or table(obj) or cell(obj))
} // end fIsTable()
// Following buffer is local to fIsHead()
Buffer gl_bufIsHeadNum = create(32)
//***********************
bool fIsHead(Object obj)
{ // Does DOORS consider the object a 'Heading' object?
// Heading Objects are those that display the paragraph number in the Main column in DOORS
// DOORS considerations for determining 'Heading Objects':
// [a] Objects that contain some non-null rich Heading text.
// [b] Objects that have no non-null rich Object Text and no Pictures (i.e. empty objects)
// [c] However, Cell, row header, and table header objects are NEVER headings,
// even when they contain Object Heading or are empty.
// [d] Note that invisible rich-text markup only is considered.
// This function looks at the Paragraph number of the object to determine if
// DOORS considers it a Heading.
// Notes:
// [1] Normal Text Object Paragraph Numbers have a ZeroDash and look like this: "3.2.1.0-4".
// Notice there is a dash after the last period.
// [2] Normal Headings Numbers have no dash and look like: "3.2.1".
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this:
// "3.2.1.0-4.2"; notice there is a period after the last dash.
// [4] Level 1 Headings paragraphs have no dashes nor periods, and look like "1".
// [5] Level 1 Text paragraphs have no periods, but do contain a dash, and look like "0-1".
// [6] Objects in tables (cell, row, table) have para numbers like nested text objects: "3-2.0-1.0-1".
// This function would correctly identifies them as Text without an explicit check,
// but to save time and string table space a specific table-row-cell check is made.
// Strategy: Get the paragraph 'number' of the object.
// If its in a table its not a Heading
// If it contains no dash then its a heading.
// If it has a dash but there is a period following the last dash, then its a heading.
// Otherwise (there's a dash with no period after it) then its not a Heading object.
if (null obj) return(false)
int LocDash, LocDashLast, LocDashNext, LocPeriod // Locations in the paragraph number
if (fIsTable (obj)) return(false) // Table-Row-Cell objects are not Headings.
gl_bufIsHeadNum = number(obj) // Put the Paragraph in the buffer
LocDash = contains(gl_bufIsHeadNum, '-', 0)
if (LocDash < 0) return(true) // No dashes at all, must be a heading (e.g. "2" or "3.2.1")
// Find the last dash in the Paragraph Number
LocDashLast = LocDash
LocDashNext = LocDash
while (LocDashNext > 0)
{ LocDashNext = contains(gl_bufIsHeadNum, '-', LocDashLast+1)
// print "\t" tempStringOf(gl_bufIsHeadNum) "\t" LocDash "\t" LocDashNext "\n"
if (LocDashNext > 0) LocDashLast = LocDashNext
}
// Find any period after the last dash:
LocPeriod = contains(gl_bufIsHeadNum, '.', LocDashLast+1)
// print "fIsHead\t" (stringOf(gl_bufIsHeadNum)) "\t" LocDash "\t" LocPeriod "\n"
return(LocPeriod > LocDashLast) // Its a heading if there's a period after the last Dash
} // end fIsHead()
Object oHead = obj
while (!null oHead and !fIsHead(oHead))
{ oHead = parent(oHead)
}
if (null oHead) //
then obj.attrDXLName = "NoHeading"
else obj.attrDXLName = number(oHead)
|
Re: Getting parent header number llandale - Tue Jan 10 15:44:52 EST 2012 WARNING: I just realized the attr-DXL solution below fails to take into account:
Use Attr-DXL.
It seems the requirement is that it will display the object's own paragraph number if its a heading, or if its a text object then display the nearest ancestor's Heading. Thus in your example, the attr-DXL will display "3.1" for both your objects. Perhaps the name of the target attribute is "dxlSectionNumber".
//**************************
bool fIsTable(Object obj)
{ // Is the object part of a DOORS table?
if (null obj) return(false)
return (row(obj) or table(obj) or cell(obj))
} // end fIsTable()
// Following buffer is local to fIsHead()
Buffer gl_bufIsHeadNum = create(32)
//***********************
bool fIsHead(Object obj)
{ // Does DOORS consider the object a 'Heading' object?
// Heading Objects are those that display the paragraph number in the Main column in DOORS
// DOORS considerations for determining 'Heading Objects':
// [a] Objects that contain some non-null rich Heading text.
// [b] Objects that have no non-null rich Object Text and no Pictures (i.e. empty objects)
// [c] However, Cell, row header, and table header objects are NEVER headings,
// even when they contain Object Heading or are empty.
// [d] Note that invisible rich-text markup only is considered.
// This function looks at the Paragraph number of the object to determine if
// DOORS considers it a Heading.
// Notes:
// [1] Normal Text Object Paragraph Numbers have a ZeroDash and look like this: "3.2.1.0-4".
// Notice there is a dash after the last period.
// [2] Normal Headings Numbers have no dash and look like: "3.2.1".
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this:
// "3.2.1.0-4.2"; notice there is a period after the last dash.
// [4] Level 1 Headings paragraphs have no dashes nor periods, and look like "1".
// [5] Level 1 Text paragraphs have no periods, but do contain a dash, and look like "0-1".
// [6] Objects in tables (cell, row, table) have para numbers like nested text objects: "3-2.0-1.0-1".
// This function would correctly identifies them as Text without an explicit check,
// but to save time and string table space a specific table-row-cell check is made.
// Strategy: Get the paragraph 'number' of the object.
// If its in a table its not a Heading
// If it contains no dash then its a heading.
// If it has a dash but there is a period following the last dash, then its a heading.
// Otherwise (there's a dash with no period after it) then its not a Heading object.
if (null obj) return(false)
int LocDash, LocDashLast, LocDashNext, LocPeriod // Locations in the paragraph number
if (fIsTable (obj)) return(false) // Table-Row-Cell objects are not Headings.
gl_bufIsHeadNum = number(obj) // Put the Paragraph in the buffer
LocDash = contains(gl_bufIsHeadNum, '-', 0)
if (LocDash < 0) return(true) // No dashes at all, must be a heading (e.g. "2" or "3.2.1")
// Find the last dash in the Paragraph Number
LocDashLast = LocDash
LocDashNext = LocDash
while (LocDashNext > 0)
{ LocDashNext = contains(gl_bufIsHeadNum, '-', LocDashLast+1)
// print "\t" tempStringOf(gl_bufIsHeadNum) "\t" LocDash "\t" LocDashNext "\n"
if (LocDashNext > 0) LocDashLast = LocDashNext
}
// Find any period after the last dash:
LocPeriod = contains(gl_bufIsHeadNum, '.', LocDashLast+1)
// print "fIsHead\t" (stringOf(gl_bufIsHeadNum)) "\t" LocDash "\t" LocPeriod "\n"
return(LocPeriod > LocDashLast) // Its a heading if there's a period after the last Dash
} // end fIsHead()
Object oHead = obj
while (!null oHead and !fIsHead(oHead))
{ oHead = parent(oHead)
}
if (null oHead) //
then obj.attrDXLName = "NoHeading"
else obj.attrDXLName = number(oHead)
|
Re: Getting parent header number kbmurphy - Tue Jan 10 19:48:45 EST 2012
Cannot find it now, but it seems to me I wrote a big sarcastic bewildering paragraph of all the yeah's and neah's and the exceptions and exceptions to the exceptions -- at least all the ones I could think of -- and ended suggesting to "forget that" and to parse the paragraph number itself to determine if its a heading, as fIsHead() does. This is a sound approach, determining if it is a heading rather than trying to determine if it should be a heading. And surely its far faster then retrieving text/string attr values. I will concede however that the desire to determine if DOORS says its a heading may be inadequate; if you want to display the "section text" with a text object you may very well look up until you find any Object Heading. That is, you really want a "Spec Heading" not a "DOORS Heading", in the rare cases they are not the same. -Louie |
Re: Getting parent header number I use an algorithm like
void skSplitOn(char ch, Buffer b, Skip skParaLevels) {
bool hasMoreThanOne = false;
int indexOfSeparator = -1;
int firstSep = -1;
int lastSep = 0;
int counter = 0;
while (lastSep != length(b)) {
if (null(b)) break;
if (length(stringOf(b)) == 0) break;
if (length(b) < 2) break;
int startingIndex = firstSep + 1;
lastSep = contains(b, ch, startingIndex)
if (lastSep == -1) {
lastSep = length(b);
}
string myParamStr = b[ startingIndex : (lastSep-1) ];
if (length(myParamStr) > 0) {
counter++;
bool putValue = put(skParaLevels, counter, myParamStr);
}
firstSep = lastSep;
} // while
}
bool strContains(string str, char ch) {
int i;
bool found = false;
for (i = 0; i < length(str); i++) {
if (str[i] == ch) {
found = true;
break;
}
}
return found;
}
void headingParaNumberOf(Object o){
Buffer b = create();
Skip skParaLevels = create();
b += number(o);
skSplitOn('.', b, skParaLevels)
setempty(b);
print("The paragraph " (number(o) ));
string strLevel;
bool first = true;
bool pureHeading = true;
string headingStr = "";
for strLevel in skParaLevels do {
if (strContains(strLevel, '-')) {
pureHeading = false;
break;
}
if (!first) {
b += ".";
}
b += strLevel;
first = false;
}
if (pureHeading) {
print(" is a heading\n");
} else {
print(" has heading " stringOf(b) "\n");
}
delete(b);
delete(skParaLevels);
}
headingParaNumberOf((Object current));
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this: // "3.2.1.0-4.2"; notice there is a period after the last dash.
|
Re: Getting parent header number SystemAdmin - Wed Jan 11 17:04:45 EST 2012 I use an algorithm like
void skSplitOn(char ch, Buffer b, Skip skParaLevels) {
bool hasMoreThanOne = false;
int indexOfSeparator = -1;
int firstSep = -1;
int lastSep = 0;
int counter = 0;
while (lastSep != length(b)) {
if (null(b)) break;
if (length(stringOf(b)) == 0) break;
if (length(b) < 2) break;
int startingIndex = firstSep + 1;
lastSep = contains(b, ch, startingIndex)
if (lastSep == -1) {
lastSep = length(b);
}
string myParamStr = b[ startingIndex : (lastSep-1) ];
if (length(myParamStr) > 0) {
counter++;
bool putValue = put(skParaLevels, counter, myParamStr);
}
firstSep = lastSep;
} // while
}
bool strContains(string str, char ch) {
int i;
bool found = false;
for (i = 0; i < length(str); i++) {
if (str[i] == ch) {
found = true;
break;
}
}
return found;
}
void headingParaNumberOf(Object o){
Buffer b = create();
Skip skParaLevels = create();
b += number(o);
skSplitOn('.', b, skParaLevels)
setempty(b);
print("The paragraph " (number(o) ));
string strLevel;
bool first = true;
bool pureHeading = true;
string headingStr = "";
for strLevel in skParaLevels do {
if (strContains(strLevel, '-')) {
pureHeading = false;
break;
}
if (!first) {
b += ".";
}
b += strLevel;
first = false;
}
if (pureHeading) {
print(" is a heading\n");
} else {
print(" has heading " stringOf(b) "\n");
}
delete(b);
delete(skParaLevels);
}
headingParaNumberOf((Object current));
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this: // "3.2.1.0-4.2"; notice there is a period after the last dash.
Notice heading C is a child of text object B, something that doesn't make sense in the paper specification world; and I cannot think of any other situation where it would be appropriate. Now create text object D below C and run your code on D. It finds A not C because B is not pure. Seems to me that the parent section of D is still C, even though C is placed incorrectly in the module (likely it "should" be below A not B). My code works if you really want to find the object that DOORS displays as its heading; but your desire to find the "pure" heading may have a lot of value, IMO so long as you add the notion of looking for actual Heading Text as well. Perhaps a "pretty" heading is one with a "pure" paragraph number and some Heading to display. In fact, I think my one report script will do just that now that you've brought it to my attention.
The above situation prompted me to write my "checkHierarchy.dxl" script, that checks for the above and several other non-spec-like structures..
I've got a "fGetTitle(Object)" function that gets the heading text and paragraph number of the parent object, but adds looking for Object Short Text as well. This is real handy when making reports for folks who deal only with paper specs. |
Re: Getting parent header number llandale - Tue Jan 10 15:44:52 EST 2012 WARNING: I just realized the attr-DXL solution below fails to take into account:
Use Attr-DXL.
It seems the requirement is that it will display the object's own paragraph number if its a heading, or if its a text object then display the nearest ancestor's Heading. Thus in your example, the attr-DXL will display "3.1" for both your objects. Perhaps the name of the target attribute is "dxlSectionNumber".
//**************************
bool fIsTable(Object obj)
{ // Is the object part of a DOORS table?
if (null obj) return(false)
return (row(obj) or table(obj) or cell(obj))
} // end fIsTable()
// Following buffer is local to fIsHead()
Buffer gl_bufIsHeadNum = create(32)
//***********************
bool fIsHead(Object obj)
{ // Does DOORS consider the object a 'Heading' object?
// Heading Objects are those that display the paragraph number in the Main column in DOORS
// DOORS considerations for determining 'Heading Objects':
// [a] Objects that contain some non-null rich Heading text.
// [b] Objects that have no non-null rich Object Text and no Pictures (i.e. empty objects)
// [c] However, Cell, row header, and table header objects are NEVER headings,
// even when they contain Object Heading or are empty.
// [d] Note that invisible rich-text markup only is considered.
// This function looks at the Paragraph number of the object to determine if
// DOORS considers it a Heading.
// Notes:
// [1] Normal Text Object Paragraph Numbers have a ZeroDash and look like this: "3.2.1.0-4".
// Notice there is a dash after the last period.
// [2] Normal Headings Numbers have no dash and look like: "3.2.1".
// [3] When a Heading is (incorrectly) a child of a Text Object, its Para looks like this:
// "3.2.1.0-4.2"; notice there is a period after the last dash.
// [4] Level 1 Headings paragraphs have no dashes nor periods, and look like "1".
// [5] Level 1 Text paragraphs have no periods, but do contain a dash, and look like "0-1".
// [6] Objects in tables (cell, row, table) have para numbers like nested text objects: "3-2.0-1.0-1".
// This function would correctly identifies them as Text without an explicit check,
// but to save time and string table space a specific table-row-cell check is made.
// Strategy: Get the paragraph 'number' of the object.
// If its in a table its not a Heading
// If it contains no dash then its a heading.
// If it has a dash but there is a period following the last dash, then its a heading.
// Otherwise (there's a dash with no period after it) then its not a Heading object.
if (null obj) return(false)
int LocDash, LocDashLast, LocDashNext, LocPeriod // Locations in the paragraph number
if (fIsTable (obj)) return(false) // Table-Row-Cell objects are not Headings.
gl_bufIsHeadNum = number(obj) // Put the Paragraph in the buffer
LocDash = contains(gl_bufIsHeadNum, '-', 0)
if (LocDash < 0) return(true) // No dashes at all, must be a heading (e.g. "2" or "3.2.1")
// Find the last dash in the Paragraph Number
LocDashLast = LocDash
LocDashNext = LocDash
while (LocDashNext > 0)
{ LocDashNext = contains(gl_bufIsHeadNum, '-', LocDashLast+1)
// print "\t" tempStringOf(gl_bufIsHeadNum) "\t" LocDash "\t" LocDashNext "\n"
if (LocDashNext > 0) LocDashLast = LocDashNext
}
// Find any period after the last dash:
LocPeriod = contains(gl_bufIsHeadNum, '.', LocDashLast+1)
// print "fIsHead\t" (stringOf(gl_bufIsHeadNum)) "\t" LocDash "\t" LocPeriod "\n"
return(LocPeriod > LocDashLast) // Its a heading if there's a period after the last Dash
} // end fIsHead()
Object oHead = obj
while (!null oHead and !fIsHead(oHead))
{ oHead = parent(oHead)
}
if (null oHead) //
then obj.attrDXLName = "NoHeading"
else obj.attrDXLName = number(oHead)
What could be added to this to display the heading number and heading eg...'3.2.2.2 Data Collection'? Thanks. |
Re: Getting parent header number bmohamed - Wed Oct 29 12:32:01 EDT 2014 What could be added to this to display the heading number and heading eg...'3.2.2.2 Data Collection'? Thanks. that should just be:
Line 72: else obj.attrDXLName = number (oHead) ": " oHead."Object Heading" ""
|
Re: Getting parent header number Mike.Scharnow - Wed Oct 29 13:01:57 EDT 2014 that should just be:
Line 72: else obj.attrDXLName = number (oHead) ": " oHead."Object Heading" ""
Perfect. Thanks. |